home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / dev / src / spr12.lha / remove1.c < prev    next >
C/C++ Source or Header  |  1995-10-31  |  4KB  |  225 lines

  1.  
  2. #include <exec/types.h>
  3. #include <exec/execbase.h>
  4. #include <exec/tasks.h>
  5. #include <clib/exec_protos.h>
  6. #include <pragmas/exec_sysbase_pragmas.h>
  7.  
  8. GLOBAL UBYTE patchStart;
  9. GLOBAL UBYTE patchEnd;
  10. GLOBAL UBYTE codeStart;
  11. GLOBAL UBYTE codeEnd;
  12.  
  13. GLOBAL ULONG UCount_Offset;
  14. GLOBAL ULONG SigBit_Offset;
  15. GLOBAL ULONG Task_Offset;
  16. GLOBAL ULONG RtsNop_Offset;
  17.  
  18. GLOBAL struct ExecBase *SysBase;
  19. GLOBAL struct Library *LibBase;
  20. GLOBAL ULONG LVO;
  21. GLOBAL ULONG (*OldRoutine)();
  22.  
  23. /*
  24. ||
  25. || Remove the patch and free it's storage.
  26. ||
  27. || "patch" points to the beginning of the patches storage.
  28. ||
  29. */
  30. LONG
  31. remove( UBYTE *patch )
  32. {
  33.    UBYTE *pc;
  34.    ULONG *ucount;
  35.    ULONG *sigbit;
  36.    struct Task **task;
  37.    UWORD *rtsnop;
  38.    UBYTE *vecBeg;
  39.    UBYTE *vecEnd;
  40.    struct Node *node;
  41.    ULONG count;
  42.  
  43.    /*
  44.    ||
  45.    || Protect.
  46.    ||
  47.    */
  48.    Forbid();
  49.  
  50.    /*
  51.    ||
  52.    || Replace our vector with the original.
  53.    ||
  54.    */
  55.    SetFunction( LibBase, LVO, OldRoutine );
  56.  
  57.    /*
  58.    ||
  59.    || Calculate variable addresses.
  60.    ||
  61.    */
  62.    ucount = ( ULONG * )        ( patch + UCount_Offset );
  63.    sigbit = ( ULONG * )        ( patch + SigBit_Offset );
  64.    task   = ( struct Task ** ) ( patch + Task_Offset   );
  65.    rtsnop = ( UWORD *)         ( patch + RtsNop_Offset );
  66.  
  67.    /*
  68.    ||
  69.    || Calculate library vector start and end address.
  70.    ||
  71.    */
  72.    vecBeg = ( (UBYTE *)LibBase ) + LVO;
  73.    vecEnd = vecBeg + LIB_VECTSIZE;
  74.  
  75.    /*
  76.    ||
  77.    || Setup signaling info.
  78.    ||
  79.    */
  80.    *sigbit = AllocSignal( -1 );
  81.    *task = FindTask( NULL );
  82.  
  83.    /*
  84.    ||
  85.    || Count the number of tasks executing within our code.
  86.    ||
  87.    */
  88.    for ( node = SysBase->TaskReady.lh_Head ; node->ln_Succ ; node = node->ln_Succ )
  89.    {
  90.       pc = (UBYTE *) *( (ULONG *) ( (struct Task *) node )->tc_SPReg );
  91.       if ( ( pc >= vecBeg && pc < vecEnd )  ||
  92.            ( pc >= &codeStart && pc < &codeEnd ) )
  93.       {
  94.          (*ucount)++;
  95.       }
  96.    }
  97.  
  98.    /*
  99.    ||
  100.    || Count the number of tasks executing within our code.
  101.    ||
  102.    */
  103.    for ( node = SysBase->TaskWait.lh_Head ; node->ln_Succ ; node = node->ln_Succ )
  104.    {
  105.       pc = (UBYTE *) *( (ULONG *) ( (struct Task *) node )->tc_SPReg );
  106.       if ( ( pc >= vecBeg && pc < vecEnd )  ||
  107.            ( pc >= &codeStart && pc < &codeEnd ) )
  108.       {
  109.          (*ucount)++;
  110.       }
  111.    }
  112.  
  113.    /*
  114.    ||
  115.    || Cache use count.
  116.    ||
  117.    */
  118.    count = *ucount;
  119.  
  120.    /*
  121.    ||
  122.    || Now change the RTS at the end of our routine to a NOP to activate
  123.    || removal code.
  124.    ||
  125.    */
  126.    *rtsnop = 0x4e71;
  127.  
  128.    /*
  129.    ||
  130.    || Flush the cache.
  131.    ||
  132.    */
  133.    CacheClearU();
  134.  
  135.    /*
  136.    ||
  137.    || Enable task switching.
  138.    ||
  139.    */
  140.    Permit();
  141.  
  142.    /*
  143.    ||
  144.    || Wait for the patch to signal us, only if the use count is not zero.
  145.    ||
  146.    */
  147.    if ( count != 0 )
  148.    {
  149.       Wait( *sigbit );
  150.  
  151.       /*
  152.       ||
  153.       || Wait until the final patch exits.
  154.       ||
  155.       */
  156.       do
  157.       {
  158.          /*
  159.          ||
  160.          || Wait a little bit.
  161.          ||
  162.          */
  163.          Delay(50);
  164.  
  165.          /*
  166.          ||
  167.          || Initialize variable.
  168.          ||
  169.          */
  170.          count = 0;
  171.  
  172.          /*
  173.          ||
  174.          || Count the number of tasks executing within our code.
  175.          ||
  176.          */
  177.          for ( node = SysBase->TaskReady.lh_Head ; node->ln_Succ ; node = node->ln_Succ )
  178.          {
  179.             pc = (UBYTE *) *( (ULONG *) ( (struct Task *) node )->tc_SPReg );
  180.             if ( ( pc >= vecBeg && pc < vecEnd )  ||
  181.                  ( pc >= &codeStart && pc < &codeEnd ) )
  182.             {
  183.                count++;
  184.             }
  185.          }
  186.    
  187.          /*
  188.          ||
  189.          || Count the number of tasks executing within our code.
  190.          ||
  191.          */
  192.          for ( node = SysBase->TaskWait.lh_Head ; node->ln_Succ ; node = node->ln_Succ )
  193.          {
  194.             pc = (UBYTE *) *( (ULONG *) ( (struct Task *) node )->tc_SPReg );
  195.             if ( ( pc >= vecBeg && pc < vecEnd )  ||
  196.                  ( pc >= &codeStart && pc < &codeEnd ) )
  197.             {
  198.                count++;
  199.             } 
  200.          }
  201.       } while ( count != 0 );
  202.    }
  203.  
  204.    /*
  205.    ||
  206.    || Free the signal.
  207.    ||
  208.    */
  209.    FreeSignal( *sigbit );
  210.  
  211.    /*
  212.    ||
  213.    || Now free the patch storage.
  214.    ||
  215.    */
  216.    FreeVec( patch );
  217.  
  218.    /*
  219.    ||
  220.    || We're done.
  221.    ||
  222.    */
  223.    return 0;
  224. }
  225.